package com.partition.mysql.biz;



import com.partition.mysql.bean.PartitionInfo;
import com.partition.mysql.bean.PartitionItem;
import com.partition.mysql.constant.SqlConstant;
import com.partition.mysql.utils.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;

/**
 * 操作数据库分区manager
 *
 * @author hexinglin
 * @created 2022-04-08 16:46
 **/
@Component
public class PartitionManager {
    /**
     * 日志
     */
    protected final Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    JdbcTemplate jdbcTemplate;

    /*
    * 查询表的分区信息
    */
    public List<PartitionInfo> queryPartitionInfos(String tableName){
        String sql = String.format(SqlConstant.FIND_TABLE_PARTITION, tableName);
        try {
            return jdbcTemplate.query(sql, new PartitionInfo());
        }catch (Exception e) {
            logger.error("查询表：{}的分区信息失败，{}",tableName,e.getMessage());
            throw new RuntimeException();
        }

    }

    /*
    * 对表增加联合索引
    */
    public void alertPrimaryKey(String tableName,String columnName){
        String sql = String.format(SqlConstant.ALTER_PRIMARY_KEY, tableName,columnName);
        try {
            jdbcTemplate.execute(sql);
        }catch (Exception e) {
            logger.error("表：{}增加联合索引，{}",tableName,e.getMessage());
            throw new RuntimeException();
        }
    }

    /*
     *删除分区
     */
    public void deletePartition(String tableName,List<String> partitions){
        if (CollectionUtils.isEmpty(partitions)){
            return;
        }
        String partitionStr = String.join(",",partitions);
        String sql = String.format(SqlConstant.DELETE_PARTITION_BY, tableName,partitionStr);
        try {
            jdbcTemplate.execute(sql);
        }catch (Exception e) {
            logger.error("表：{}删除分区:{}失败，{}",tableName,partitionStr,e.getMessage());
            throw new RuntimeException();
        }
    }

    /*
     *初始化分区
     */
    public void initPartition(PartitionItem item){
        //构建分区信息
        Map<String, Long> map = DateUtils.getDateMap(item.getRangeStrategy(), item.getPreNums());
        StringBuilder sb = new StringBuilder();
        map.forEach(new BiConsumer<String, Long>() {
            @Override
            public void accept(String key, Long value) {
                logger.info("表：{}初始化分区:p{}",item.getTableName(),key);
                sb.append(String.format(SqlConstant.PARTITION_BASIC_STRPARTI,key,value)).append(",");
            }
        });
        String baseStr = sb.substring(0,sb.length() - 1);

        String sql = String.format(SqlConstant.DEFAULT_PARTITION_BY,item.getTableName(),item.getRangeColumnName(),baseStr);

        try {
            jdbcTemplate.execute(sql);
        }catch (Exception e) {
            logger.error("表：{}初始化分区:{}失败，{}",item.getTableName(),sql,e.getMessage());
            throw new RuntimeException();
        }
    }

    /*
     *添加分区
     */
    public void addPartition(String tableName,String partName,Long time){

        String baseStr =String.format(SqlConstant.PARTITION_BASIC_STRPARTI,partName,time) ;

        String sql = String.format(SqlConstant.ADD_PARTITION_BY,tableName,baseStr);

        try {
            logger.info("表：{}添加分区:p{}",tableName,partName);
            jdbcTemplate.execute(sql);
        }catch (Exception e) {
            logger.error("表：{}增加分区:{}失败，{}",tableName,partName,e.getMessage());
            throw new RuntimeException();
        }
    }

    /*
     *添加分区
     */
    public void addPartitionByMap(String tableName,Map<String, Long> map){
        if (map.isEmpty()){
            return;
        }
        StringBuilder sb = new StringBuilder();
        map.forEach(new BiConsumer<String, Long>() {
            @Override
            public void accept(String key, Long value) {
                logger.info("表：{}添加表分区:p{}",tableName,key);
                sb.append(String.format(SqlConstant.PARTITION_BASIC_STRPARTI,key,value)).append(",");
            }
        });
        String baseStr = sb.substring(0,sb.length() - 1);

        String sql = String.format(SqlConstant.ADD_PARTITION_BY,tableName,baseStr);

        try {
            jdbcTemplate.execute(sql);
        }catch (Exception e) {
            logger.error("表：{}增加分区:{}失败，{}",tableName,sql,e.getMessage());
            throw new RuntimeException();
        }
    }
}
